﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using JupiterLibrary;
using KinectXNATools;
using KinectUserManager;
using KinnectInput.KinectMetro.VideoPlayer;

namespace KinnectInput.KinectMetro
{
    public enum KinectMetroMenuState
    {
        Colapsed,
        Iniciated,
        Active
    }
    public delegate void MenuEnterEventHandler(EventArgs e);
    public delegate void MenuLeaveEventHandler(EventArgs e);
    public class KinectMetroMenu
    {
        Ring SelectionRing;
        Sprite BackGroundText;
        Sprite ManoPlanaText;
        Rectangle ManoSize;
        public Rectangle BackGroundTarget { get; set; }
        public KinectMetroMenuState MenuState { get; set; }
        public Ring MenuRing{get; private set;}
        public bool handStillUp;
        
        public event MenuEnterEventHandler MenuEnter;
        public event MenuLeaveEventHandler MenuLeave;
        public KinectMetroCardContainer[] Containers { get; private set; }
        public KinectMetroCardContainer BackButtonContainer { get; private set; }
        UserAsserter UserAssertion;
        Rectangle ScreenBounds;
        public KinectMetroVideoPlayer InfoVideoPlayer { get; private set; }
        public GraphicsDevice GraphicsDevice { get; private set; }
        public virtual void OnEnterMenu(EventArgs e)
        {
            if (e != null)
            {
                e = new EventArgs();
                this.MenuState = KinectMetroMenuState.Active;
                this.MenuRing.EndAngle = 0;
                this.MenuRing.Update();
                this.Update(false);
            }
        }
        public virtual void OnLeaveMenu(EventArgs e)
        {
            if (e != null)
            {
                e = new EventArgs();
                this.MenuState = KinectMetroMenuState.Colapsed;
                this.InfoVideoPlayer.isVisible = false;
            }
        }
        public KinectMetroMenu(Texture2D backgroundText, Rectangle backGroundTarget, GraphicsDevice graphicsDevice, UserAsserter userAss, Texture2D manoTex)
        {
            this.GraphicsDevice = graphicsDevice;
            this.ScreenBounds = graphicsDevice.Viewport.Bounds;
            this.UserAssertion = userAss;
            this.BackGroundText = new Sprite();
            this.BackGroundText.Texture = backgroundText;
            this.ManoPlanaText = new Sprite();
            this.ManoPlanaText.SetRectangle(manoTex.Bounds);
            this.ManoPlanaText.Texture = manoTex;
            this.ManoPlanaText.Update();
            this.ManoSize = manoTex.Bounds;
            this.BackGroundText.SetRectangle(backGroundTarget);
            //this.BackGroundText.UseMatrix = true;
            this.BackGroundTarget = backGroundTarget;
            this.BackGroundText.Update();
            
            MenuState = KinectMetroMenuState.Colapsed;
            //MenuRing
            MenuRing=new Ring(0, 0, 75,15);
            MenuRing.Position = new Vector3(200, 200, 0);
            MenuRing.Color = Color.Green;
            MenuRing.Update();
            //SelectionRing
            SelectionRing = new Ring(0, 0, 75, 15);
            SelectionRing.Position = new Vector3(200, 200, 0);
            SelectionRing.Color = Color.Orange;
            SelectionRing.Update();
            //events
            this.MenuEnter += new MenuEnterEventHandler(KinectMetroMenu_MenuEnter);
            this.MenuLeave += new MenuLeaveEventHandler(KinectMetroMenu_MenuLeave);

            this.Containers = new KinectMetroCardContainer[3];
            
            Vector2 containerPos=new Vector2((graphicsDevice.Viewport.Bounds.Width/2)-(((this.Containers.Length*MenuItemSizes.VerticalCardContainer.Width)+(MenuItemSizes.separation*2))/2),(graphicsDevice.Viewport.Bounds.Height/2)-(MenuItemSizes.VerticalCardContainer.Height/2));
            Vector2 groupPos=new Vector2(MenuItemSizes.separation,MenuItemSizes.separation);
            
            
            Rectangle backButtonRect=MenuItemSizes.SquareButton;
            KinectMetroButtonGrp BackGrp=new KinectMetroButtonGrp(MenuItemSizes.SquareButton,Vector2.Zero,MenuStyle.graphicsDevice);
            //falta implemntar el boton back y funcion add single button
            
            //laksdjhfklas
            KinectMetroIconButton backButton = new KinectMetroIconButton(Vector2.Zero, MenuItemSizes.SquareButton, null, Jupiter.Content.Load<Texture2D>("Icons/Back"));
            BackGrp.addSingleButton(backButton);
            backButton.Build(BackGrp);
            
            
            this.BackButtonContainer = new KinectMetroCardContainer(new Vector2(graphicsDevice.Viewport.Width - (MenuItemSizes.SquareButton.Width + (MenuItemSizes.separation * 2)), MenuItemSizes.separation), new KinectMetroButtonGrp[] { BackGrp });
            BackGrp.BuildGroup(BackButtonContainer);

            //override no contemplado para haccer en un container un solo area

            BackGrp.Update();
            backButton.Update();

            for (int x = 0; x < Containers.Length; x++)
            {
                KinectMetroButtonGrp[] ButtonGroups = new KinectMetroButtonGrp[2];
                for (int y = 0; y < ButtonGroups.Length; y++)
                {
                    ButtonGroups[y] = new KinectMetroButtonGrp(MenuItemSizes.ButtonGrp, groupPos, graphicsDevice);
                    groupPos.Y += MenuItemSizes.ButtonGrp.Height + MenuItemSizes.separation;
                }
                Containers[x] = new KinectMetroCardContainer(containerPos, ButtonGroups);
                //reseteo posicion
                groupPos.Y = MenuItemSizes.separation;
                containerPos.X += +ButtonGroups[0].Bounds.Width + MenuItemSizes.separation;
            }

            Microsoft.Xna.Framework.Media.Video navetaVideo = Jupiter.Content.Load<Microsoft.Xna.Framework.Media.Video>("Video/NavetaMovie");
            Rectangle offsetRect = new Rectangle(0, 0, 200, 200);
            offsetRect.Width = navetaVideo.Width;
            offsetRect.Height = navetaVideo.Height;
            offsetRect.Width *= 2;
            offsetRect.Height *= 2;
            Point pos = new Point((graphicsDevice.Viewport.Width / 2) - (offsetRect.Width / 2), (graphicsDevice.Viewport.Height / 2) - (offsetRect.Height / 2));
            this.InfoVideoPlayer = new KinectMetroVideoPlayer(navetaVideo,offsetRect,this,pos);
            
            Containers[1].ButtonGroups[0].Pushed += new ClickEventHandler(VideoPlayerPushed);
            Containers[1].ButtonGroups[0].Release += new ReleasedEventHandler(VideoPlayerRelease);
            InfoVideoPlayer.ButtonBar.ButtonGroups[0].Pushed += new ClickEventHandler(PlayerMovie_Pushed);
            InfoVideoPlayer.ButtonBar.ButtonGroups[1].Pushed += new ClickEventHandler(PauserMovie_Pushed);
            InfoVideoPlayer.ButtonBar.ButtonGroups[2].Pushed += new ClickEventHandler(StopperMovie_Pushed);

            InfoVideoPlayer.ButtonBar.ButtonGroups[0].Release += new ReleasedEventHandler(PlayerMovie_Release);
            InfoVideoPlayer.ButtonBar.ButtonGroups[1].Release += new ReleasedEventHandler(PauserMovie_Release);
            InfoVideoPlayer.ButtonBar.ButtonGroups[2].Release += new ReleasedEventHandler(StopperMovie_Release);

            InfoVideoPlayer.ButtonBar.ButtonGroups[0].LeaveArea += new ItemAreaLeaveHandler(MenuButton_LeaveArea);
            InfoVideoPlayer.ButtonBar.ButtonGroups[1].LeaveArea += new ItemAreaLeaveHandler(MenuButton_LeaveArea);
            InfoVideoPlayer.ButtonBar.ButtonGroups[2].LeaveArea += new ItemAreaLeaveHandler(MenuButton_LeaveArea);

            BackButtonContainer.ButtonGroups[0].Release += new ReleasedEventHandler(BackButton_Release);
            BackButtonContainer.ButtonGroups[0].Pushed += new ClickEventHandler(BackButton_Pushed);
            BackButtonContainer.ButtonGroups[0].LeaveArea += new ItemAreaLeaveHandler(MenuButton_LeaveArea);

            for (int x = 0; x < this.Containers.Length; x++)
            {
                for (int y = 0; y < this.Containers[x].ButtonGroups.Length; y++)
                {
                    Containers[x].ButtonGroups[y].LeaveArea += new ItemAreaLeaveHandler(MenuButton_LeaveArea);
                }
            }

            //live areas de todos los botones
        }

        void MenuButton_LeaveArea(object sender, EventArgs e)
        {
            ResetSelectionRing();
        }

        void BackButton_Pushed(object sender, ProximityClickEventArgs e)
        {
            if (InfoVideoPlayer.isVisible)
            {
                InfoVideoPlayer.isVisible = false;
                InfoVideoPlayer.Update();
                InfoVideoPlayer.kill_speechControll();
            }
            else
            {
                this.MenuState = KinectMetroMenuState.Colapsed;
            }
        }

        void BackButton_Release(object sender, EventArgs e)
        {
            if (InfoVideoPlayer.isVisible)
            {
                InfoVideoPlayer.isVisible = false;
                InfoVideoPlayer.Update();
                InfoVideoPlayer.kill_speechControll();
            }
            else
            {
                this.MenuState = KinectMetroMenuState.Colapsed;
            }
        }

        void StopperMovie_Release(object sender, EventArgs e)
        {
            InfoVideoPlayer.myPlayer.Stop();
        }

        void PauserMovie_Release(object sender, EventArgs e)
        {
            InfoVideoPlayer.myPlayer.Pause();
        }

        void PlayerMovie_Release(object sender, EventArgs e)
        {
            if (InfoVideoPlayer.myPlayer.State == Microsoft.Xna.Framework.Media.MediaState.Stopped)
            {
                InfoVideoPlayer.myPlayer.Resume();
            }
            else
            {
                InfoVideoPlayer.myPlayer.Play(InfoVideoPlayer.movie);
            }
        }

        void StopperMovie_Pushed(object sender, ProximityClickEventArgs e)
        {
            InfoVideoPlayer.myPlayer.Stop();
        }

        void PauserMovie_Pushed(object sender, ProximityClickEventArgs e)
        {
            InfoVideoPlayer.myPlayer.Pause();
        }

        void PlayerMovie_Pushed(object sender, ProximityClickEventArgs e)
        {
            if (InfoVideoPlayer.myPlayer.State == Microsoft.Xna.Framework.Media.MediaState.Stopped)
            {
                InfoVideoPlayer.myPlayer.Resume();
            }
            else
            {
                InfoVideoPlayer.myPlayer.Play(InfoVideoPlayer.movie);
            }
        }

        void VideoPlayerRelease(object sender, EventArgs e)
        {
            InfoVideoPlayer.isVisible = true;
            InfoVideoPlayer.myPlayer.Play(InfoVideoPlayer.movie);
        }

        void VideoPlayerPushed(object sender, ProximityClickEventArgs e)
        {
            InfoVideoPlayer.isVisible = true;
            InfoVideoPlayer.myPlayer.Play(InfoVideoPlayer.movie);
        }
        //Rutina Relleno automatico de botones
        public void FillButtonGroup(Texture2D IconTexture, string [] text, GraphicsDevice graphicsDevice)
        {
            for (int x = 0; x < Containers.Length; x++)
            {
                for (int y = 0; y < Containers[x].ButtonGroups.Length; y++)
                {
                    if (Containers[x].ButtonGroups[y].Buttons.Count<1)
                    {
                        KinectMetroIconButton btn00 = new KinectMetroIconButton(Vector2.Zero, MenuItemSizes.SquareButton, MenuStyle.ButtonBackGround, IconTexture);
                        Containers[x].ButtonGroups[y].addButton(btn00);
                        btn00.Build(Containers[x].ButtonGroups[y]);

                        KinectMetroIconButton btn01 = new KinectMetroIconButton(Vector2.Zero, MenuItemSizes.SquareButton, MenuStyle.ButtonBackGround, null);
                        Containers[x].ButtonGroups[y].addButton(btn01);
                        btn01.Build(Containers[x].ButtonGroups[y]);

                        KinectMetroStringButton KMStrBtn = new KinectMetroStringButton(Vector2.Zero, MenuItemSizes.LongHorizontalButton, MenuStyle.ButtonBackGround, text);
                        Containers[x].ButtonGroups[y].addButton(KMStrBtn);
                        KMStrBtn.Build(Containers[x].ButtonGroups[y]);
                        return;
                    }
                }
            }
            
                        
        }
        void KinectMetroMenu_MenuLeave(EventArgs e)
        {
            this.MenuState = KinectMetroMenuState.Colapsed;
            
        }

        void KinectMetroMenu_MenuEnter(EventArgs e)
        {
            this.MenuState = KinectMetroMenuState.Active;
        }
        public void Inicialize(UserAsserter usAsr){
            this.UserAssertion = usAsr;
        }
        public void Update(bool isOverHead)
        {   //comprobar que no sea null el input si lo es no hace falta hacer update
            if (UserAssertion != null)
            {
                //pillamos las cooredenas de la mano mouse de kinect
                Point p = XNAMathHelper.ToPoint(UserAssertion.getMouseHand(this.ScreenBounds.Width, this.ScreenBounds.Height));
                Rectangle manoTarget = new Rectangle(p.X - (ManoSize.Width / 2), p.Y - (ManoSize.Height / 2), ManoSize.Width, ManoSize.Height);
                //Ipdate pa dibujar la mano
                ManoPlanaText.SetRectangle(manoTarget);
                ManoPlanaText.Update();
                //comprobamos que no este activo, esto mandara sobre subir o bajar del menu
                KinectMetroButtonGrp selectedGroup = null;
                if (this.MenuState == KinectMetroMenuState.Active)
                {
                    Vector3 mouseHandVector = XNAMathHelper.ToVector3(p);
                    if (this.InfoVideoPlayer.isVisible)
                    {
                        InfoVideoPlayer.Update();
                        

                        //posiciono el selection ring
                        SelectionRing.Position = mouseHandVector;

                        for (int x = 0; x < this.InfoVideoPlayer.ButtonBar.ButtonGroups.Length; x++)
                        {

                            if (this.InfoVideoPlayer.ButtonBar.ButtonGroups[x].Contains(this.InfoVideoPlayer.ButtonBar.ButtonGroups[x].Bounds, manoTarget.Center))
                            {
                                if (!(this.InfoVideoPlayer.ButtonBar.ButtonGroups[x].wasContined))
                                {
                                    InfoVideoPlayer.ButtonBar.ButtonGroups[x].OnEnterArea(new EnterAreaEventArgs(mouseHandVector));
                                }
                                //actualizo historial
                                InfoVideoPlayer.ButtonBar.ButtonGroups[x].wasContined = true;
                                selectedGroup = InfoVideoPlayer.ButtonBar.ButtonGroups[x];
                                
                            }
                            //provocar evento on leave
                            else if (this.InfoVideoPlayer.ButtonBar.ButtonGroups[x].wasContined)
                            {
                                this.InfoVideoPlayer.ButtonBar.ButtonGroups[x].wasContined = false;
                                this.InfoVideoPlayer.ButtonBar.ButtonGroups[x].OnLeveArea(new EventArgs());
                            }
                        }

                        if (selectedGroup == null)
                        {
                            if (SelectionRing.EndAngle < 361 && BackButtonContainer.ButtonGroups[0].Bounds.Contains(manoTarget.Center))
                            {
                                SelectionRing.Position = mouseHandVector;
                                SelectionRing.EndAngle += Jupiter.AtXSeconds(2f, 361);
                                SelectionRing.Update();
                            }
                            else if (SelectionRing.EndAngle > 360)
                            {
                                BackButtonContainer.ButtonGroups[0].OnReleased(new EventArgs());
                                ResetSelectionRing();
                            }
                            else if (SelectionRing.EndAngle > 0)
                            {
                                ResetSelectionRing();
                            }
                        }
                        // osea si hay selectedGroup disponible
                        else
                        {
                            //primero que se pase de 360
                            SelectionRing.Position = mouseHandVector;
                            SelectionRing.EndAngle += Jupiter.AtXSeconds(2f, 361);
                            SelectionRing.Update();

                            //si se pasa reseteo selection ring y tiro el evento
                            if (SelectionRing.EndAngle > 360)
                            {
                                selectedGroup.OnReleased(new EventArgs());
                                ResetSelectionRing();
                            }
                        }
                        

                    }
                    else 
                    {
                        
                        for (int x = 0; x < this.Containers.Length; x++)
                        {
                        //region update normal para mouse y movimento
                            this.Containers[x].Update();

                            for (int y = 0; y < this.Containers[x].ButtonGroups.Length; y++)
                            {
                                if (Containers[x].ButtonGroups[y].Contains(Containers[x].ButtonGroups[y].Bounds, manoTarget.Center))
                                {
                                    //actualizo el historial de presencia de la mano kinect sobre el boton
                                    if (!(Containers[x].ButtonGroups[y].wasContined))
                                    {
                                        Containers[x].ButtonGroups[y].OnEnterArea(new EnterAreaEventArgs(mouseHandVector));
                                    }
                                    selectedGroup = Containers[x].ButtonGroups[y];
                                    
                                    Containers[x].ButtonGroups[y].wasContined = true;
    
                                }
                                else if (Containers[x].ButtonGroups[y].wasContined)
                                {
                                    Containers[x].ButtonGroups[y].wasContined = false;
                                    Containers[x].ButtonGroups[y].OnLeveArea(new EventArgs());
                                }
                            }
                        }
                        if (selectedGroup == null)
                        {
                            if (SelectionRing.EndAngle < 361 && BackButtonContainer.ButtonGroups[0].Bounds.Contains(manoTarget.Center))
                            {
                                SelectionRing.Position = mouseHandVector;
                                SelectionRing.EndAngle += Jupiter.AtXSeconds(2f, 361);
                                SelectionRing.Update();
                            }
                            else if (SelectionRing.EndAngle > 360)
                            {
                                BackButtonContainer.ButtonGroups[0].OnReleased(new EventArgs());
                                ResetSelectionRing();
                            }
                            else if (SelectionRing.EndAngle > 0)
                            {
                                ResetSelectionRing();
                            }
                        }
                        else
                        {
                            SelectionRing.Position = mouseHandVector;
                            SelectionRing.EndAngle += Jupiter.AtXSeconds(2f, 361);
                            SelectionRing.Update();

                            if (SelectionRing.EndAngle > 360)
                            {
                                SelectionRing.EndAngle = 0;
                                selectedGroup.OnReleased(new EventArgs());
                            }
                        }
                    }
                    this.BackButtonContainer.Update();
                }
                else
                {
                    UpdateMenuRing(isOverHead, manoTarget);
                }
            }
            
            
        }
        private void UpdateMenuRing(bool isOverHead, Rectangle manoTarget)
        {
            #region OverHead
            if (isOverHead)
            {
                if (MenuRing.EndAngle < 360)
                {
                    this.MenuRing.EndAngle += Jupiter.AtXSeconds(0.5f, 361);
                    MenuRing.Update();
                }
                else
                {
                    if (MenuState == KinectMetroMenuState.Active && !handStillUp)
                    {
                        handStillUp = false;
                        OnLeaveMenu(new EventArgs());
                    }
                    else if (MenuState == KinectMetroMenuState.Colapsed && !handStillUp)
                    {
                        handStillUp = false;
                        OnEnterMenu(new EventArgs());
                    }
                    handStillUp = true;
                }
            }
            #endregion OverHead
            #region MenuInActive
            else
            {
                handStillUp = false;
                this.MenuRing.EndAngle = 0;
                MenuRing.Update();
                
            }
            #endregion MenuInActive
        }
        void ResetSelectionRing()
        {
            SelectionRing.EndAngle = 0;
            SelectionRing.Update();
        }
        public void Draw()
        {
            if (this.MenuState == KinectMetroMenuState.Active)
            {
                BackGroundText.Draw();
                //esto es degub para ver el button group 
                
                //this.BackButtonContainer.ButtonGroups[0].backGroundText.Draw();

                this.BackButtonContainer.Draw();
                if (InfoVideoPlayer.isVisible)
                {
                    InfoVideoPlayer.Draw();
                }
                else
                {
                    foreach (KinectMetroCardContainer kmcc in this.Containers)
                    {
                        kmcc.Draw();
                    }
                }
                //se teine que ver el selection ring por encima del videoplayer
                if (SelectionRing.EndAngle > 0)
                    SelectionRing.Draw();
                
                ManoPlanaText.Draw();
                
            }
            if (MenuRing.EndAngle > 1)
            {
                MenuRing.Draw();
            }
        }
        public void DrawTextButtons(SpriteBatch sb, SpriteFont sf)
        {
            for (int x = 0; x < Containers.Length; x++)
            {
                for (int y = 0; y < Containers[x].ButtonGroups.Length; y++)
                {
                    for (int n = 0; n < Containers[x].ButtonGroups[y].Buttons.Count; n++)
                    {
                        if (Containers[x].ButtonGroups[y].Buttons[n].GetType() == typeof(KinectMetroStringButton))
                        {
                            KinectMetroStringButton KMSB = (KinectMetroStringButton)Containers[x].ButtonGroups[y].Buttons[n];
                            KMSB.DrawString(sb);
                        }
                    }
                }
            }

        }
    }
}
